package org.infosec.lc.exercises.springAspect;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.infosec.lc.exercises.ImportSpringContext;
import org.infosec.lc.exercises.springAspect.DeclareParents.Seller;
import org.infosec.lc.exercises.springAspect.DeclareParents.Waiter;
import org.infosec.lc.exercises.springAspect.annotations.TestBean;

/**
	文件名：SampleAspects.java
	作  者：林超
	时  间：2011-4-12下午12:22:03

	功能描述：测试Spring AOP Aspect 
	
 */
@Aspect		//①通过该注解将PreGreetingAspect标识为一个切面
public class SampleAspects {
	
	protected final transient Log log = LogFactory.getLog(getClass());
	
	//execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)
	@Before("execution(* org.infosec.lc.exercises.springAspect..*.*(..))")
//	@Before("execution(* *..*.*(..))")
	public void doBeforeInServicLayer(JoinPoint joinPoint){
		log.debug("在....之前执行");
		System.out.println(joinPoint.getSignature().getName());
	    System.out.println(this.getClass().getSimpleName() + " : Aop: do before in Service layer ");
	}

	/**---************ 以上 code 也可将Pointcut(切入点)及Advice(建议、通知)分开 ****************---*/
	// 定义Pointcut
	@Pointcut("execution(* org.infosec.lc.exercises.springAspect..*.*(..))")
	public void inServiceLayer(){
		
	}
	/**
	 * Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分，一是表达式，如第36行；二是方法签名，如第37行。
	 * 方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符，因为表达式不直观，
	 * 因此我们可以通过方法签名的方式为此表达式命名。
	 * 因此Pointcut中的方法只需要方法签名，而不需要在方法体内编写实际代码。
	 */
	
	//定义Advice
//	@Before("org.infosec.lc.exercises.springAspect.inServiceLayer()")
//	public void logInfo(){
//		log.debug("在....之前执行");
//		System.out.println();
//	    System.out.println(this.getClass().getSimpleName() + " : Aop: do before in Service layer ");
//	}
	/**
	 * 单独定义Pointcut的好处是，一是通过使用有意义的方法名，而不是难读的Pointcut表达式，使代码更加直观；
	 * 二是Pointcut可以实现共享，被多个Advice直接调用。若有多个Advice调用某个Pointcut，而这个Pointcut的表达式在将来有改变时，
	 * 只需修改一个地方，维护更加方便。
	 */
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//测试@Before
		AspectClient aopClient = (AspectClient) ImportSpringContext.ctx.getBean("aspectClient");
		aopClient.AopClient();
		
		//测试@DeclareParents
		Waiter waiter = (Waiter)ImportSpringContext.ctx.getBean("waiterImpl"); 
		waiter.greetTo("John"); 
		Seller seller = (Seller)waiter; //①可以成功进行强制类型转换 
		seller.sell("Beer", "John"); 
		
		//测试@AfterReturning -_- Annotation
		org.infosec.lc.exercises.springAspect.annotations.Waiter naiveWaiter = (org.infosec.lc.exercises.springAspect.annotations.Waiter) ImportSpringContext.ctx.getBean("naiveWaiter");
		org.infosec.lc.exercises.springAspect.annotations.Waiter naughtyWaiter = (org.infosec.lc.exercises.springAspect.annotations.Waiter) ImportSpringContext.ctx.getBean("naughtyWaiter");
		naiveWaiter.greetTo("John"); 	//①该方法未被织入增强
		naughtyWaiter.greetTo("Tom");	//②该方法被织入增强 
		
		TestBean t = (TestBean) ImportSpringContext.ctx.getBean("testBean");
//		try {
//			List<Bean> l = t.testAnn(1,"s");
			t.testAnn(1,"s");
//			for(Bean s:l){
//				System.out.println(s.getName() + "---" + s.getAge());
//			}
//		} catch (Exception e) {
//			
//			System.out.println("++++++++++++++++++++++++++++++");
//			e.printStackTrace();
//		}
	}
}

